package cn.liumouren.jzxd.service.impl;

import cn.liumouren.jzxd.common.utils.PageUtils;
import cn.liumouren.jzxd.common.utils.Query;
import cn.liumouren.jzxd.dao.*;
import cn.liumouren.jzxd.entity.Likes;
import cn.liumouren.jzxd.entity.Zone;
import cn.liumouren.jzxd.entity.middle.SceneZone;
import cn.liumouren.jzxd.service.ZoneService;
import cn.liumouren.jzxd.utils.mapperUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;


@Service("zoneService")
public class ZoneServiceImpl extends ServiceImpl<ZoneDao, Zone> implements ZoneService {
    @Resource
    private PictureDao pictureDao;
    @Resource
    private ZoneDao zoneDao;
    @Resource
    private UserDao userDao;
    @Resource
    private LikesDao likesDao;
    @Autowired
    private SceneZoneDao sceneZoneDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<Zone> page = this.page(
                new Query<Zone>().getPage(params),
                new QueryWrapper<Zone>()
        );

        return new PageUtils(page);
    }

    @Override
//    @Cacheable(value = "zone", key = "#id", cacheManager = "cacheManagerOneDay")
    public Zone getById(Serializable id) {
        Zone zone = super.getById(id);
        zone.setUser(userDao.selectById(zone.getUserId()));
        mapperUtils.getUrlsByEntity(zone, pictureDao);
        return zone;
    }

    @Override
    public IPage<Zone> findByUserId(String userId, int cur, int size) {
        IPage<Zone> zones = super.page(new Page<Zone>(cur, size, true), new QueryWrapper<Zone>().lambda()
                .eq(Zone::getUserId, userId)
                .orderByDesc(Zone::getAddTime));
        List<Zone> records = zones.getRecords();
        mapperUtils.getUrlsByEntity(records, pictureDao);
        zones.setRecords(records);
        return zones;
    }

    @Override
    public IPage<Zone> getLikedZonesByUserId(String userId, int cur, int size) {
//        IPage<Zone> zones = zoneDao.getLikedZonesByUserId(userId, new Page<Zone>(cur, size, false));

        Page<Likes> likesPage = likesDao.selectPage(new Page<Likes>(cur, size), new LambdaQueryWrapper<Likes>()
                .select(Likes::getZoneId)
                .eq(Likes::getUserId, userId)
                .orderByDesc(Likes::getAddTime));

        List<Likes> records = likesPage.getRecords();
        List<String> zoneIds = records.stream().map(Likes::getZoneId).collect(Collectors.toList());
        List<Zone> zones = baseMapper.selectBatchIds(zoneIds);

        Page<Zone> page = new Page<>();
//        mapperUtils.getUrlsByEntity(zones, pictureDao); //zone列表显示图片
        page.setRecords(zones);
        page.setCurrent(cur);
        page.setSize(size);
        return page;
    }

    @Override
    public IPage<Zone> getCommentedZonesByUserId(String userId, int cur, int size) {
        IPage<Zone> zones = zoneDao.getCommentedZonesByUserId(new Page<Zone>(cur, size, false), userId);
        return zones;  // 不显示图片
        // 列表显示图片
//        return mapperUtils.getUrlsByEntity(zones, pictureDao);
    }

    @Override
    public void makePrivacyOrPublic(String zoneId, int state) {
        baseMapper.update(null, new UpdateWrapper<Zone>().lambda()
                .set(Zone::getPrivacy, state)
                .eq(Zone::getId, zoneId));
    }

    @Override
    public List<Zone> pageQuery(int cur, int size) {
        List<Zone> zones = baseMapper.selectList(new QueryWrapper<Zone>().lambda()
                .eq(Zone::getPrivacy, 0)  //公开动态
                .orderByDesc(Zone::getAddTime)  //按时间降序
                .last(" limit " + (cur - 1) * size + "," + size));
        mapperUtils.getUserByEntity(zones, userDao);
        return mapperUtils.getUrlsByEntity(zones, pictureDao);
    }

    @Override
    public IPage<Zone> pageQueryByColumn(Map<String, Integer> map, int cur, int size) {
        // [{'add_time':1},{'hot':0}]
        Integer value;
        String key;
        QueryWrapper<Zone> queryWrapper = new QueryWrapper<>();
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            value = entry.getValue();
            key = entry.getKey();
            if (value == 0) {
                // 0升序
                queryWrapper.orderByAsc(key);
            } else if (value == 1) {
                // 降序
                queryWrapper.orderByDesc(key);
            }
        }
        IPage<Zone> zones = baseMapper.selectPage(new Page<Zone>(cur, size, false), queryWrapper);
        return zones;
    }

    @Override
    public List<Zone> getRelatedZones(String sceneId, int cur, int size) {
        IPage<SceneZone> page = sceneZoneDao.selectPage(new Page<SceneZone>(cur, size), new LambdaQueryWrapper<SceneZone>().eq(SceneZone::getSceneId, sceneId));
        List<SceneZone> sceneZones = page.getRecords();
        ArrayList<Zone> zones = new ArrayList<>();
        for (SceneZone sceneZone : sceneZones) {
            Zone zone = baseMapper.selectById(sceneZone.getZoneId());
            zones.add(zone);
        }
        return zones;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(Zone entity) {
        String zoneId = IdWorker.getIdStr();
        entity.setId(zoneId);
        entity.setAddTime(new Date());
        // 在picture表关联 xxxId
        mapperUtils.associatePicturesAndEntity(entity, pictureDao);
        // 关联zone和scene
        associateSceneAndZone(entity);
        return super.save(entity);
    }

    private void associateSceneAndZone(Zone entity) {
        if (!StringUtils.isBlank(entity.getSceneIds())) {
            String sceneIdsStr = entity.getSceneIds();
            String[] sceneIds = sceneIdsStr.split(";");
            SceneZone sceneZone = new SceneZone();
            sceneZone.setZoneId(entity.getId());
            for (String sceneId : sceneIds) {
                sceneZone.setId(IdWorker.getIdStr());
                sceneZone.setSceneId(sceneId);
                sceneZoneDao.insert(sceneZone);
            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(Zone entity) {
        return SqlHelper.retBool(baseMapper.updateById(entity));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIds(Collection<? extends Serializable> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return false;
        }
        // 删除 scene_zone 中间表数据
        sceneZoneDao.delete(new QueryWrapper<SceneZone>().lambda()
                .in(SceneZone::getZoneId, idList));
        return SqlHelper.retBool(baseMapper.deleteBatchIds(idList));
    }


}